#ifndef XENENGIN_SANDBOX3D_HPP
#define XENENGIN_SANDBOX3D_HPP

#include "xen/xen.hpp"

#include "GL/glew.h"

class SandBox3D: public Xen::Layer {
public:
    SandBox3D()
        :Layer("SandBox3D"),
        dirlight_({{0.2, 0.2, 0.2}, {0.8, 0.8, 0.8}, {0.8, 0.8, 0.8}}, {0, -1, -1}),
        dotlight_({{0.0, 0.2, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}, {1, 0.7, 0.8}, {0, 0, -8}),
        spotlight_({{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}}, {20, 30}, {-1, 0, -6}, {0, 0, -1})
    {
        controller_ = std::make_unique<Xen::PerspectiveCameraController>(
                45,
                static_cast<float>(Xen::Application::Get().GetWindow().GetSize().w)/Xen::Application::Get().GetWindow().GetSize().h,
                0.01, 100
                );

        std::vector<Xen::Vertex> rect_vertices = {
            {{0.5f,  0.5f, 0}, {1, 1}, {0, 0, 1}, {0, 1, 0}},  // right top
            {{-0.5f,  0.5f,0}, {0, 1}, {0, 0, 1}, {0, 1, 0}},  // left top
            {{-0.5f, -0.5f,0}, {0, 0}, {0, 0, 1}, {0, 1, 0}},  // left bottom
            {{0.5f, -0.5f, 0}, {1, 0}, {0, 0, 1}, {0, 1, 0}}   // right bottom
        };

        std::vector<uint32_t> indices = {
            0, 1, 2,
            0, 2, 3
        };

        auto material1 = Xen::Renderer3D::CreateMaterial();
        material1->SetTexture("material.diffuse_texture", library_.Load("dotlight", "sandbox/assets/textures/dotlight.png"));

        dotlight_mesh_ = Xen::Mesh::Create(rect_vertices, indices);
        dotlight_mesh_->SetMaterial(material1);

        auto material2 = Xen::Renderer3D::CreateMaterial();
        material2->SetTexture("material.diffuse_texture", library_.Load("spotlight", "sandbox/assets/textures/spotlight.png"));

        spotlight_mesh_ = Xen::Mesh::Create(rect_vertices, indices);
        spotlight_mesh_->SetMaterial(material2);

        // model_ = Xen::ModelLoader::Create(library_, "sandbox/assets/textures/Basketball/Bball.dae");
        // model_ = Xen::ModelLoader::Create(library_, "sandbox/assets/textures/Whispy Woods/Whispy_fix.dae");
        // model_ = Xen::ModelLoader::Create(library_, "sandbox/assets/textures/SoccerBall/soccerball.dae");
        model_ = Xen::ModelLoader::Create(library_, "sandbox/assets/textures/nanosuit/nanosuit.obj");

        auto skybox = Xen::Renderer3D::CreateSkyBox(
                "sandbox/assets/textures/skybox/top.jpg",
                "sandbox/assets/textures/skybox/bottom.jpg",
                "sandbox/assets/textures/skybox/left.jpg",
                "sandbox/assets/textures/skybox/right.jpg",
                "sandbox/assets/textures/skybox/front.jpg",
                "sandbox/assets/textures/skybox/back.jpg"
                );
        Xen::Renderer3D::SetSkyBox(skybox);
    }

    void OnUpdate(Xen::TimeStep ts) override {
        Xen::RenderCommand::SetClearColor({1, 1, 1, 1});
        Xen::RenderCommand::Clear();

        Xen::Renderer3D::BeginScene(controller_->GetCamera(), dirlight_, dotlight_, spotlight_);
        {
            glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
            Xen::Renderer3D::EnableFaceCull();
            // Xen::Renderer3D::EnableFaceCull();
            Xen::Renderer3D::DrawMesh(dotlight_mesh_, {dotlight_.position.x, dotlight_.position.y, dotlight_.position.z}, {0, controller_->GetCamera().GetRotation().y, 0}); 
            Xen::Renderer3D::DrawMesh(spotlight_mesh_, {spotlight_.position.x, spotlight_.position.y, spotlight_.position.z}, {0, controller_->GetCamera().GetRotation().y, 0}); 
            Xen::Renderer3D::DrawModel(model_, {0, -3, -12}, {0, -90, 0}, {1, 1, 1});

            if (show_skybox_) {
                Xen::Renderer3D::DrawSkyBox();
            }
        }
        Xen::Renderer3D::EndScene();

        controller_->OnUpdate(ts);
    }

    void OnImGuiRender() override {
        ImGui::Begin("Command Panel");
        if (ImGui::Button("Toggle SkyBox")) {
            show_skybox_ = !show_skybox_;
        }
        if (ImGui::BeginTabBar("DirectLight", ImGuiTabBarFlags_None)) {
            if (ImGui::BeginTabItem("DirectLight")) {
                if (ImGui::Button("TrunOff")) {
                    dirlight_.phong.ambient = glm::vec3(0, 0, 0);
                    dirlight_.phong.diffuse = glm::vec3(0, 0, 0);
                    dirlight_.phong.specular = glm::vec3(0, 0, 0);
                }
                ImGui::SliderFloat("ambient.x", &dirlight_.phong.ambient.x, 0, 1);
                ImGui::SliderFloat("ambient.y", &dirlight_.phong.ambient.y, 0, 1);
                ImGui::SliderFloat("ambient.z", &dirlight_.phong.ambient.z, 0, 1);

                ImGui::SliderFloat("diffuse.x", &dirlight_.phong.diffuse.x, 0, 1);
                ImGui::SliderFloat("diffuse.y", &dirlight_.phong.diffuse.y, 0, 1);
                ImGui::SliderFloat("diffuse.z", &dirlight_.phong.diffuse.z, 0, 1);

                ImGui::SliderFloat("specular.x", &dirlight_.phong.specular.x, 0, 1);
                ImGui::SliderFloat("specular.y", &dirlight_.phong.specular.y, 0, 1);
                ImGui::SliderFloat("specular.z", &dirlight_.phong.specular.z, 0, 1);

                ImGui::SliderFloat("direction.x", &dirlight_.direction.x, -1, 1);
                ImGui::SliderFloat("direction.y", &dirlight_.direction.y, -1, 1);
                ImGui::SliderFloat("direction.z", &dirlight_.direction.z, -1, 1);
                ImGui::EndTabItem();
            }

            if (ImGui::BeginTabItem("DotLight")) {
                if (ImGui::Button("TrunOff")) {
                    dotlight_.phong.ambient = glm::vec3(0, 0, 0);
                    dotlight_.phong.diffuse = glm::vec3(0, 0, 0);
                    dotlight_.phong.specular = glm::vec3(0, 0, 0);
                }
                ImGui::SliderFloat("ambient.x", &dotlight_.phong.ambient.x, 0, 1);
                ImGui::SliderFloat("ambient.y", &dotlight_.phong.ambient.y, 0, 1);
                ImGui::SliderFloat("ambient.z", &dotlight_.phong.ambient.z, 0, 1);

                ImGui::SliderFloat("diffuse.x", &dotlight_.phong.diffuse.x, 0, 1);
                ImGui::SliderFloat("diffuse.y", &dotlight_.phong.diffuse.y, 0, 1);
                ImGui::SliderFloat("diffuse.z", &dotlight_.phong.diffuse.z, 0, 1);

                ImGui::SliderFloat("specular.x", &dotlight_.phong.specular.x, 0, 1);
                ImGui::SliderFloat("specular.y", &dotlight_.phong.specular.y, 0, 1);
                ImGui::SliderFloat("specular.z", &dotlight_.phong.specular.z, 0, 1);

                ImGui::SliderFloat("position.x", &dotlight_.position.x, -10, 10);
                ImGui::SliderFloat("position.y", &dotlight_.position.y, -10, 10);
                ImGui::SliderFloat("position.z", &dotlight_.position.z, -10, 10);
                ImGui::EndTabItem();
            }

            if (ImGui::BeginTabItem("SpotLight")) {
                if (ImGui::Button("TrunOff")) {
                    spotlight_.phong.ambient = glm::vec3(0, 0, 0);
                    spotlight_.phong.diffuse = glm::vec3(0, 0, 0);
                    spotlight_.phong.specular = glm::vec3(0, 0, 0);
                }
                ImGui::SliderFloat("ambient.x", &spotlight_.phong.ambient.x, 0, 1);
                ImGui::SliderFloat("ambient.y", &spotlight_.phong.ambient.y, 0, 1);
                ImGui::SliderFloat("ambient.z", &spotlight_.phong.ambient.z, 0, 1);

                ImGui::SliderFloat("diffuse.x", &spotlight_.phong.diffuse.x, 0, 1);
                ImGui::SliderFloat("diffuse.y", &spotlight_.phong.diffuse.y, 0, 1);
                ImGui::SliderFloat("diffuse.z", &spotlight_.phong.diffuse.z, 0, 1);

                ImGui::SliderFloat("specular.x", &spotlight_.phong.specular.x, 0, 1);
                ImGui::SliderFloat("specular.y", &spotlight_.phong.specular.y, 0, 1);
                ImGui::SliderFloat("specular.z", &spotlight_.phong.specular.z, 0, 1);

                ImGui::SliderFloat("position.x", &spotlight_.position.x, -10, 10);
                ImGui::SliderFloat("position.y", &spotlight_.position.y, -10, 10);
                ImGui::SliderFloat("position.z", &spotlight_.position.z, -10, 10);
                ImGui::EndTabItem();
            }
            ImGui::EndTabBar();
        }
        ImGui::End();
    }

    void OnEvent(Xen::Event &event) override {
        controller_->OnEvent(event);
    }

private:
    std::unique_ptr<Xen::PerspectiveCameraController> controller_;

    Xen::Ref<Xen::Model> model_;
    Xen::Ref<Xen::Mesh> dirlight_mesh_;
    Xen::Ref<Xen::Mesh> dotlight_mesh_;
    Xen::Ref<Xen::Mesh> spotlight_mesh_;

    Xen::Texture2DLibrary library_;
    Xen::DirectLight dirlight_;
    Xen::DotLight dotlight_;
    Xen::SpotLight spotlight_;
    bool show_skybox_ = false;
};

#endif
